import os
import shutil
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                            QLabel, QPushButton, QListWidget, QTextEdit, 
                            QProgressBar, QFileDialog, QMessageBox, QDialog)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont


class FolderSelectionDialog(QDialog):
    """文件夹多选对话框（支持添加父文件夹及子文件夹）"""
    def __init__(self, parent=None, caption="选择文件夹", directory=""):
        super().__init__(parent)
        self.setWindowTitle(caption)
        self.resize(600, 400)
        
        self.selected_folders = []
        self.current_dir = directory
        
        # 创建布局
        layout = QVBoxLayout(self)
        
        # 列表显示已选文件夹
        self.list_view = QListWidget()
        layout.addWidget(self.list_view)
        
        # 按钮区（新增"添加父文件夹"按钮）
        btn_layout = QHBoxLayout()
        
        self.add_btn = QPushButton("添加单个文件夹")
        self.add_btn.clicked.connect(self.add_folder)
        btn_layout.addWidget(self.add_btn)
        
        self.add_parent_btn = QPushButton("添加父文件夹（包含子文件夹）")
        self.add_parent_btn.clicked.connect(self.add_parent_folder)
        btn_layout.addWidget(self.add_parent_btn)
        
        self.remove_btn = QPushButton("移除选中")
        self.remove_btn.clicked.connect(self.remove_folder)
        btn_layout.addWidget(self.remove_btn)
        
        self.ok_btn = QPushButton("确定")
        self.ok_btn.clicked.connect(self.accept)
        btn_layout.addWidget(self.ok_btn)
        
        self.cancel_btn = QPushButton("取消")
        self.cancel_btn.clicked.connect(self.reject)
        btn_layout.addWidget(self.cancel_btn)
        
        layout.addLayout(btn_layout)
    
    def add_folder(self):
        """添加单个文件夹"""
        folder = QFileDialog.getExistingDirectory(
            self, "选择单个文件夹", self.current_dir
        )
        if folder and folder not in self.selected_folders:
            self.selected_folders.append(folder)
            self.list_view.addItem(folder)
            self.current_dir = folder  # 更新当前目录
    
    def add_parent_folder(self):
        """添加父文件夹，并自动导入其所有直接子文件夹"""
        parent_folder = QFileDialog.getExistingDirectory(
            self, "选择父文件夹", self.current_dir
        )
        if not parent_folder:
            return
        
        # 获取父文件夹下的所有直接子文件夹（不递归）
        try:
            subfolders = []
            for entry in os.scandir(parent_folder):
                if entry.is_dir() and not entry.name.startswith('.'):  # 排除隐藏文件夹
                    subfolders.append(entry.path)
            
            if not subfolders:
                QMessageBox.information(self, "提示", f"所选父文件夹下没有子文件夹")
                return
            
            # 添加所有子文件夹（去重）
            added_count = 0
            for folder in subfolders:
                if folder not in self.selected_folders:
                    self.selected_folders.append(folder)
                    self.list_view.addItem(folder)
                    added_count += 1
            
            self.current_dir = parent_folder  # 更新当前目录
            QMessageBox.information(self, "成功", f"已添加 {added_count} 个子文件夹（共 {len(subfolders)} 个）")
        
        except Exception as e:
            QMessageBox.critical(self, "错误", f"获取子文件夹失败：{str(e)}")
    
    def remove_folder(self):
        """移除选中的文件夹"""
        for item in self.list_view.selectedItems():
            row = self.list_view.row(item)
            del self.selected_folders[row]
            self.list_view.takeItem(row)
    
    def get_folders(self):
        """返回选中的文件夹列表"""
        return self.selected_folders


class MultiFolderCopyGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("多文件夹批量复制工具")
        self.resize(900, 650)
        self.setMinimumSize(800, 600)
        
        # 存储选择的路径
        self.items_to_copy = []  # 合并后的待复制项（文件+文件夹）
        self.target_folders = []  # 目标文件夹列表
        
        # 初始化界面
        self.init_ui()
        
        # 当前路径（用于对话框初始目录）
        self.current_path = os.path.dirname(os.path.abspath(__file__))

    def init_ui(self):
        # 主Widget和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(8)
        
        # -------------------------- 1. 待复制项选择区域 --------------------------
        # 标题
        source_label = QLabel("1. 选择需要复制的文件或文件夹:")
        source_label.setFont(QFont("微软雅黑", 10, QFont.Bold))
        main_layout.addWidget(source_label)
        
        # 选择按钮区
        source_btn_layout = QHBoxLayout()
        main_layout.addLayout(source_btn_layout)
        
        self.add_file_btn = QPushButton("添加文件...")
        self.add_file_btn.clicked.connect(self.add_files)
        source_btn_layout.addWidget(self.add_file_btn)
        
        self.add_folder_btn = QPushButton("添加文件夹...")
        self.add_folder_btn.clicked.connect(self.add_folders)
        source_btn_layout.addWidget(self.add_folder_btn)
        
        self.clear_source_btn = QPushButton("清除全部")
        self.clear_source_btn.clicked.connect(self.clear_all_items)
        source_btn_layout.addWidget(self.clear_source_btn)
        
        # 统一的待复制列表
        self.copy_list = QListWidget()
        self.copy_list.setSelectionMode(QListWidget.ExtendedSelection)  # 支持多选
        self.copy_list.setAlternatingRowColors(True)  # 行交替颜色，增强可读性
        main_layout.addWidget(self.copy_list)
        
        # 删除选中项按钮
        self.del_item_btn = QPushButton("删除选中项")
        self.del_item_btn.clicked.connect(self.remove_selected_items)
        main_layout.addWidget(self.del_item_btn)
        
        # -------------------------- 2. 目标文件夹选择区域 --------------------------
        # 标题
        target_label = QLabel("2. 选择目标文件夹 (可多选):")
        target_label.setFont(QFont("微软雅黑", 10, QFont.Bold))
        main_layout.addWidget(target_label)
        
        # 按钮区
        target_btn_layout = QHBoxLayout()
        main_layout.addLayout(target_btn_layout)
        
        self.add_target_btn = QPushButton("添加目标文件夹...")
        self.add_target_btn.clicked.connect(self.add_target_folders)
        target_btn_layout.addWidget(self.add_target_btn)
        
        self.clear_target_btn = QPushButton("清除全部")
        self.clear_target_btn.clicked.connect(self.clear_target_folders)
        target_btn_layout.addWidget(self.clear_target_btn)
        
        # 目标文件夹列表
        self.target_list = QListWidget()
        self.target_list.setSelectionMode(QListWidget.ExtendedSelection)
        self.target_list.setAlternatingRowColors(True)
        main_layout.addWidget(self.target_list)
        
        # 删除选中目标文件夹按钮
        self.del_target_btn = QPushButton("删除选中目标文件夹")
        self.del_target_btn.clicked.connect(self.remove_selected_targets)
        main_layout.addWidget(self.del_target_btn)
        
        # -------------------------- 操作按钮区 --------------------------
        op_btn_layout = QHBoxLayout()
        main_layout.addLayout(op_btn_layout)
        
        self.start_btn = QPushButton("开始复制")
        self.start_btn.setFont(QFont("微软雅黑", 9, QFont.Bold))
        self.start_btn.setStyleSheet("background-color: #4CAF50; color: white;")
        self.start_btn.clicked.connect(self.start_copy)
        op_btn_layout.addWidget(self.start_btn)
        
        self.clear_log_btn = QPushButton("清除日志")
        self.clear_log_btn.clicked.connect(self.clear_log)
        op_btn_layout.addWidget(self.clear_log_btn)
        
        # -------------------------- 进度条 --------------------------
        progress_label = QLabel("复制进度:")
        main_layout.addWidget(progress_label)
        
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        main_layout.addWidget(self.progress_bar)
        
        # -------------------------- 日志区域 --------------------------
        log_label = QLabel("操作日志:")
        main_layout.addWidget(log_label)
        
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)  # 只读
        self.log_text.setMinimumHeight(100)
        main_layout.addWidget(self.log_text)

    # -------------------------- 待复制项操作 --------------------------
    def add_files(self):
        """添加文件到待复制列表"""
        files, _ = QFileDialog.getOpenFileNames(
            self, "选择要复制的文件", self.current_path, "所有文件 (*)"
        )
        if files:
            for file in files:
                if file not in self.items_to_copy:
                    self.items_to_copy.append(file)
                    self.copy_list.addItem(f"[文件] {file}")
            self.current_path = os.path.dirname(files[0])

    def add_folders(self):
        """添加文件夹到待复制列表（调用多选对话框）"""
        dialog = FolderSelectionDialog(
            self, "选择要复制的文件夹", self.current_path
        )
        if dialog.exec_():
            folders = dialog.get_folders()
            if folders:
                for folder in folders:
                    if folder not in self.items_to_copy:
                        self.items_to_copy.append(folder)
                        self.copy_list.addItem(f"[文件夹] {folder}")
                self.current_path = os.path.dirname(folders[0])

    def clear_all_items(self):
        """清除所有待复制项"""
        self.items_to_copy.clear()
        self.copy_list.clear()

    def remove_selected_items(self):
        """删除选中的待复制项"""
        for item in self.copy_list.selectedItems():
            row = self.copy_list.row(item)
            del self.items_to_copy[row]
            self.copy_list.takeItem(row)

    # -------------------------- 目标文件夹操作 --------------------------
    def add_target_folders(self):
        """添加目标文件夹（调用多选对话框）"""
        dialog = FolderSelectionDialog(
            self, "选择目标文件夹", self.current_path
        )
        if dialog.exec_():
            folders = dialog.get_folders()
            if folders:
                for folder in folders:
                    if folder not in self.target_folders:
                        self.target_folders.append(folder)
                        self.target_list.addItem(folder)
                self.current_path = os.path.dirname(folders[0])

    def clear_target_folders(self):
        """清除所有目标文件夹"""
        self.target_folders.clear()
        self.target_list.clear()

    def remove_selected_targets(self):
        """删除选中的目标文件夹"""
        for item in self.target_list.selectedItems():
            row = self.target_list.row(item)
            del self.target_folders[row]
            self.target_list.takeItem(row)

    # -------------------------- 日志和进度条 --------------------------
    def log(self, message):
        """添加日志信息"""
        self.log_text.append(message)
        self.log_text.moveCursor(self.log_text.textCursor().End)

    def clear_log(self):
        """清除日志"""
        self.log_text.clear()

    # -------------------------- 核心复制功能 --------------------------
    def start_copy(self):
        """开始复制操作"""
        # 验证输入
        if not self.items_to_copy:
            QMessageBox.critical(self, "错误", "请至少选择一个文件或文件夹进行复制！")
            return
        if not self.target_folders:
            QMessageBox.critical(self, "错误", "请至少选择一个目标文件夹！")
            return

        total_items = len(self.items_to_copy)
        total_targets = len(self.target_folders)
        total_operations = total_items * total_targets
        completed = 0

        self.log("===== 开始复制操作 =====")
        self.log(f"待复制项总数: {total_items} 个")
        self.log(f"目标文件夹: {total_targets} 个")

        # 遍历所有目标文件夹
        for target_idx, target_folder in enumerate(self.target_folders, 1):
            self.log(f"\n处理目标文件夹 {target_idx}/{total_targets}: {target_folder}")
            
            # 遍历所有待复制项
            for item_idx, item in enumerate(self.items_to_copy, 1):
                item_name = os.path.basename(item)
                target_path = os.path.join(target_folder, item_name)

                try:
                    os.makedirs(os.path.dirname(target_path), exist_ok=True)

                    if os.path.isfile(item):
                        shutil.copy2(item, target_path)
                        self.log(f"  文件 {item_idx}/{total_items}: {item_name} [复制成功]")
                    elif os.path.isdir(item):
                        if not os.path.exists(target_path):
                            shutil.copytree(item, target_path)
                            self.log(f"  文件夹 {item_idx}/{total_items}: {item_name} [复制成功]")
                        else:
                            self.log(f"  文件夹 {item_idx}/{total_items}: {item_name} [已存在，跳过]")
                    else:
                        self.log(f"  未知类型 {item_idx}/{total_items}: {item_name} [跳过]")

                except Exception as e:
                    self.log(f"  错误 {item_idx}/{total_items}: {item_name} → {str(e)}")

                # 更新进度
                completed += 1
                progress = int((completed / total_operations) * 100)
                self.progress_bar.setValue(progress)
                QApplication.processEvents()

        self.log("\n===== 操作完成 =====")
        QMessageBox.information(self, "完成", "所有复制操作已完成！")
        self.progress_bar.setValue(100)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    font = QFont("SimHei")
    app.setFont(font)
    window = MultiFolderCopyGUI()
    window.show()
    sys.exit(app.exec_())